/**
 * @file can_protocol.h
 * @author YangSL (dalin@main.com)
 * @brief 
 * @version 0.0.1
 * @date 2022-09-28
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#ifndef _CAN_PROTOCOL_H_
#define _CAN_PROTOCOL_H_

#include "data.h"
#include "obj_data.h"

/*macro define*/
/*函数响应码解析*/
#define      ACK                        1
#define      ACK_ERR                    -1
#define      ACK_CONTINUE               0
#define      CAN_RC_CAN_DRIVER_FAULT    -5      /**< 返回值:CAN接口函数执行失败 */
#define      CAN_RC_CMD_LEN_ERR         -4      /**< 返回值:命令数据长度不对 */
#define      CAN_RC_ID_IS_OUT           -3      /**< 返回值:目标不存在 */
#define      CAN_RC_TIMEOUT             -2      /**< 返回值:超时 */
#define      CAN_RC_ERROR               -1      /**< 返回值:出错 */
#define      CAN_RC_OK                  0       /**< 返回值:正常 */
#define      CAN_RC_DATA                1       /*接收到数据*/
#define      TIMER_NUM                  e_comp_max
/*enum define*/
enum Run_State
{
    e_init = 0 ,
    e_ready ,
    e_running ,
    e_error ,
};
enum Ack_Err
{
    e_rolling_over_err  = 0x05030000 ,
    e_sdo_time_over_err = 0x05040000 ,
    e_ccs_cmd_err       = 0x05040001 ,
    e_block_size_err    = 0x05040002 ,
    e_serial_num_err    = 0x05040003 ,
    e_crc_err           = 0x05040004 ,
    e_visit_obj_err     = 0x06010000 ,
    e_w_only_err        = 0x06010001 ,
    e_r_only_err        = 0x06010002 ,
    e_obj_invalid_err   = 0x06020000 ,
    e_pdo_map_err       = 0x06040041 ,
    e_pdo_map_len_err   = 0x06040042 ,
    e_data_len_err      = 0x06070010 ,
    e_data_len_over_err = 0x06070012 ,
    e_data_len_short_err= 0x06070013 ,
    e_subidx_invalid_err= 0x06090011 ,
    e_write_over_len_err= 0x06090030 ,
    e_para_over_big_err = 0x06090031 ,
    e_para_over_small_err=0x06090032 ,
    e_err               = 0x08000000 ,
    e_prevent_err       = 0x08000022 ,
    
    e_max_num       
};
enum client_cmd
{
    e_clt_load      = 0 ,   //客户端sdo下载命令
    e_clt_load_init = 1 ,   //客户端sdo下载启动
    e_clt_up_init   = 2 ,   //客户端sdo上载启动
    e_clt_up        = 3 ,   //客户端sdo上载命令
    e_clt_stop_cmd  = 4 ,   //客户端sdo停止命令
    e_clt_blk_up    = 5 ,   //客户端sdo块上载命令
    e_clt_blk_load  = 6 ,   //客户端sdo块下载命令
};
enum serve_cmd
{
    e_ser_up        = 0 ,   //服务器sdo上载命令
    e_ser_load      = 1 ,   //服务器sdo下载命令
    e_ser_up_init   = 2 ,   //服务器sdo上载启动
    e_ser_load_init = 3 ,   //服务器sdo下载启动
    e_ser_stop_cmd  = 4 ,   //服务器sdo停止命令
    e_ser_blk_load  = 5,    //服务器sdo块下载命令
    e_ser_blk_up    = 6,    //服务器sdo块上载命令
};
enum blk_load_cmd
{
    e_blk_load_init = 0 ,
    e_blk_load_child ,
    e_blk_load_end,
};

/*struct define*/
#pragma pack(1)

typedef union 
{
    int8_t data8[2];
    int16_t data16;
}udata16;
typedef union 
{
    int8_t data8[4];

    int32_t data32;

}udata32;
/*COB ID*/
typedef union
{
    uint32_t m_CAN_ID;
    struct 
    {
        uint32_t    m_FUN_ID   :16 ;
        uint32_t    m_DA_ID    :6  ;
        uint32_t    m_SA_ID    :6  ;
        uint32_t    m_Reserver :4  ;
    }byte;
}uCob_id;


typedef union
{
    uint32_t m_CAN_ID;
    struct 
    {
        uint32_t    m_Node_ID   :7  ;
        uint32_t    m_FUN_ID    :4  ;
        uint32_t    m_Reserver  :21  ;
    }byte;
}uCob_std_id;

/*download init cmd*/
typedef struct
{
    uint8_t s    : 1 ;
    uint8_t e    : 1 ;
    uint8_t n    : 2 ;
    uint8_t x    : 1 ;
    uint8_t ccs  : 3 ;
}sload_sect_init;
typedef struct
{
    uint8_t x    : 5 ;
    uint8_t scs  : 3 ;
}sload_sect_init_ack;
/*download section cmd*/
typedef struct
{
    uint8_t c    : 1 ;
    uint8_t n    : 3 ;
    uint8_t t    : 1 ;
    uint8_t ccs  : 3 ;
}sload_sect;
typedef struct
{
    uint8_t x    : 4 ;
    uint8_t t    : 1 ;
    uint8_t scs  : 3 ;
}sload_sect_ack;
/*upload section init cmd*/
typedef struct
{
    uint8_t x    : 5 ;
    uint8_t ccs  : 3 ;
}sup_sect_init;
typedef struct
{
    uint8_t s    : 1 ;
    uint8_t e    : 1 ;
    uint8_t n    : 2 ;
    uint8_t x    : 1 ;
    uint8_t scs  : 3 ;
}sup_sect_init_ack;
/*upload section cmd*/
typedef struct
{
    uint8_t x    : 4 ;
    uint8_t t    : 1 ;
    uint8_t ccs  : 3 ;
}sup_sect;
typedef struct
{
    uint8_t c    : 1 ;
    uint8_t n    : 3 ;
    uint8_t t    : 1 ;
    uint8_t scs  : 3 ;
}sup_sect_ack;
/*download block init cmd*/
typedef struct
{
    uint8_t cs    : 1 ;
    uint8_t s     : 1 ;
    uint8_t cc    : 1 ;
    uint8_t x     : 2 ;
    uint8_t ccs   : 3 ;
}sload_block_init;
typedef struct
{
    uint8_t ss    : 2 ;
    uint8_t sc    : 1 ;
    uint8_t x     : 2 ;
    uint8_t scs   : 3 ;
}sload_block_init_ack;
/*download sub block cmd*/
typedef struct
{
    uint8_t seqno    : 7 ;
    uint8_t c     : 1 ;
}sload_sub_block;
typedef struct
{
    uint8_t ss    : 2 ;
    uint8_t x     : 3 ;
    uint8_t scs   : 3 ;
}sload_sub_block_ack;
/*download block end cmd*/
typedef struct
{
    uint8_t cs    : 1 ;
    uint8_t x     : 1 ;
    uint8_t n     : 3 ;
    uint8_t ccs   : 3 ;
}sload_block_end;
typedef struct
{
    uint8_t ss    : 2 ;
    uint8_t sc    : 1 ;
    uint8_t x     : 2 ;
    uint8_t scs   : 3 ;
}sload_block_end_ack;
/*upload block init cmd*/
typedef struct
{
    uint8_t cs    : 2 ;
    uint8_t cc    : 1 ;
    uint8_t x     : 2 ;
    uint8_t ccs   : 3 ;
}sup_block_init1;
typedef struct
{
    uint8_t ss    : 1 ;
    uint8_t s     : 1 ;
    uint8_t sc    : 1 ;
    uint8_t x     : 2 ;
    uint8_t scs   : 3 ;
}sup_block_init_ack;
typedef struct
{
    uint8_t cs    : 2 ;
    uint8_t x     : 3 ;
    uint8_t ccs   : 3 ;
}sup_block_init2;
/*download sub block cmd*/
typedef struct
{
    uint8_t seqno : 7 ;
    uint8_t c     : 1 ;
}sup_sub_block;
typedef struct
{
    uint8_t cs    : 2 ;
    uint8_t x     : 3 ;
    uint8_t ccs   : 3 ;
}sup_sub_block_ack;
/*upload block end cmd*/
typedef struct
{
    uint8_t ss    : 2 ;
    uint8_t n     : 3 ;
    uint8_t scs   : 3 ;
}sup_block_end;
typedef struct
{
    uint8_t cs    : 1 ;
    uint8_t x     : 4 ;
    uint8_t ccs   : 3 ;
}sup_block_end_ack;
/*stop cmd*/
typedef struct
{
    uint8_t x    : 5 ;
    uint8_t cs   : 3 ;
}sstop;
/*command type*/
typedef union
{
    uint8_t m_cmd;
    sload_sect_init load_sect_init;
    sload_sect_init_ack load_sect_init_ack;
    /*download section cmd*/
    sload_sect load_sect;
    sload_sect_ack load_sect_ack;
    /*upload section init cmd*/
    sup_sect_init up_sect_init;
    sup_sect_init_ack up_sect_init_ack;
    /*upload section cmd*/
    sup_sect up_sect;
    sup_sect_ack up_sect_ack;
    /*download block init cmd*/
    sload_block_init load_block_init;
    sload_block_init_ack load_block_init_ack;
    /*download sub block cmd*/
    sload_sub_block load_sub_block;
    sload_sub_block_ack load_sub_block_ack;
    /*download block end cmd*/
    sload_block_end load_block_end;
    sload_block_end_ack load_block_end_ack;
    /*upload block init cmd*/
    sup_block_init1 up_block_init1;
    sup_block_init_ack up_block_init_ack;
    sup_block_init2 up_block_init2;
    /*download sub block cmd*/
    sup_sub_block up_sub_block;
    sup_sub_block_ack up_sub_block_ack;
    /*upload block end cmd*/
    sup_block_end up_block_end;
    sup_block_end_ack up_block_end_ack;
    /*stop cmd*/
    sstop stop_cmd;
}ucmd;
/*Data type*/
typedef union 
{
    uint8_t m_data[8];
    struct
    {
        ucmd cmd_data;
        uint16_t m_index;
        uint8_t  m_subindex;
        udata32  data;
    }type1; /* 命令帧 */
    struct
    {
        ucmd cmd_data;
        uint8_t  m_data[7];
    }type2; /* 数据帧 */

    struct 
    {
        ucmd cmd_data;
        uint16 crc16[2];
        uint8  reserve[3];
    }type_crc;
    
}udata_type;
/*CAN Frame*/
/* CAN结构体 */
typedef union 
{
    uint8_t m_data[15];
    struct
    {
        uCob_std_id m_cob_id ;
        uint8_t m_extend;
        uint8_t m_remote;
        uint8_t m_length;
        udata_type data;
    }std_byte;

    struct
    {
        uCob_id m_cob_id ;
        uint8_t m_extend;
        uint8_t m_remote;
        uint8_t m_length;
        udata_type data;
    }byte;
}ucan_frame;

typedef union 
{
   uint8_t cmd;
   struct 
   {
       uint8_t rec :5 ;  
       uint8_t cmd :3 ;
   }byte;
   
}usdo_cmd;
typedef struct 
{
    uint8_t m_sa_id ;
    usdo_cmd m_sdo_cmd ;
    sindex m_index ;
}sser_sdo_cmd;
typedef struct 
{
    uint16_t m_index ;
    uint8_t m_subindex;
}sCanIndex;

typedef struct 
{
    uint8_t m_stop_cmd;
    uint8_t m_ser_cmd ;
    uint8_t m_clt_cmd ;
    uint8_t m_ack_state ;
    uint8_t m_sdo_status;
    uint8_t m_blk_clt_cmd;
    uint8_t m_blk_clt_size;
    uint8_t m_blk_load_size ;
    uint8_t m_blk_load_ack_size ;
    bool m_blk_load_result;
    sser_sdo_cmd ser_sdo_cmd;
    ucan_frame can_pkg;
    uint32_t m_err_code;
    int8_t  m_sdo_buff[e_comp_max][512];
}scan_run_msg;
#pragma pack()

extern scan_run_msg can_run_msg;

/*static function define */
int8_t protocol_analysis(ucan_frame *can_pkg);
int8_t sdo_send(sCanIndex index,uint8* data,uint8 len);
int8_t clt_sdo_com_test(void);
#endif
